/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.essilab.analyzer.util;

import java.util.*;
import org.essilab.analyzer.Configuration.Config;

/**
 * This class takes a Map containing a list of words with their associated type
 * and replace the type with the associated weight.
 *
 * @author Mohamed-Amine Chouchene, Ahcène Idinarere, Vincent Nock, Alain
 * Janin-Manificat
 */
public class WeightOnWords {

    HashMap<String, String> motToTypeMap;
    Map<String, Float> motToWeightMap;

    /**
     * Constructor of WeightOnWords. Convert the given HashMap<String, String>
     * to a HashMap<String, Float>. Load the property file "weight.conf".
     *
     * @param motToTypeMap HashMap<String, String> - a map containing a list of
     * words with associated type.
     */
    public WeightOnWords(HashMap<String, String> motToTypeMap) {
        this.motToTypeMap = motToTypeMap;
        motToWeightMap = new TreeMap<>();
        Config.setFile("weight.conf");
        putWeight();
    }

    /**
     * Fill WeightOnWords#motToWeightMap with words and the weight associated
     * with the word type.
     *
     * @see WeightOnWords#sortFloatByValue(java.util.Map)
     */
    private void putWeight() {

        for (Map.Entry<String, String> entry : motToTypeMap.entrySet()) {
            motToWeightMap.put(entry.getKey(), Float.parseFloat(Config.get(entry.getValue())));
        }
//        long l = System.currentTimeMillis();
//        for (int i = 0; i < 10000; i++) {
//            sortFloatByValue(motToWeightMap);
//        }
//        System.out.println(System.currentTimeMillis()-l);

        motToWeightMap = sortFloatByValue(motToWeightMap);
        System.out.println(motToWeightMap);

    }

    /**
     * Sort a map by value.
     *
     * @param <K> any Class.
     * @param <V> a Class that implements Comparable<V> interface (expected
     * Float).
     * @param map Map - the map to sort by value.
     * @return Map<K,V> - a map ordered with given map hash ordered by value.
     * Note : this implementation is faster than Statistic#sortByValue but
     * expect Float as Map value.
     */
    static <K, V extends Comparable<? super V>> Map<K, V> sortFloatByValue(Map<K, V> map) {
        SortedSet<Map.Entry<K, V>> sortedEntries = new TreeSet<>(
                new Comparator<Map.Entry<K, V>>() {

                    @Override
                    public int compare(Map.Entry<K, V> e1, Map.Entry<K, V> e2) {
                        Float fa = (Float) e1.getValue();
                        Float fb = (Float) e2.getValue();
                        return (fa < fb) ? 1 : ((fa == fb) ? 0 : -1); //Use == to compare reference instead of value because Set avoid doublons.
                    }
                });
        sortedEntries.addAll(map.entrySet());
        Map<K, V> result = new LinkedHashMap<>();
        for (Map.Entry<K, V> entry : sortedEntries) {
            result.put(entry.getKey(), entry.getValue());
        }
        return result;
    }

//    public static void main(String[] args) {
//        HashMap<String, String> motToTypeMap = new HashMap<String, String>();
//        motToTypeMap.put("maison", "nom");
//        motToTypeMap.put("Robert", "prénom");
//        motToTypeMap.put("manger", "verbe");
//        motToTypeMap.put("regarder", "verbe");
//        new WeightOnWords(motToTypeMap);
//    }
}
